/* //device/system/broncho-ril/ril_util.h
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <fcntl.h>
#include <termios.h>
#ifndef BRONCHO_TEST
#include <cutils/sockets.h>
#endif

#include <utils/Log.h>
#include "at_tok.h"
#include "ril_util.h"

#undef LOG_TAG
#define LOG_TAG "RIL"
#define TTY_DEVICE_PREFIX 	"/dev/tty"
#define PLATFORM_PATH		"/proc/hwinfo"
#define  upper(ch) (ch>96 && ch<123)?(ch-32):ch


static const unsigned char _saveTopMask[] =
{
	0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe
};

static const unsigned char _bitValueMask[] =
{
	0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01
};

static const unsigned short _valueMask[] =
{
	0x0000,
	0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
	0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
};


int strStartsWith(const char *line, const char *prefix)
{
    for ( ; *line != '\0' && *prefix != '\0' ; line++, prefix++) 
	{
        if (*line != *prefix) 
		{
            return 0;
        }
    }

    return *prefix == '\0';
}

int at_line_scanf_int (char* p_cur, int* p_out)
{
	int err = 0;

	if (p_cur == NULL || p_out == NULL)
	{
		return 0;
	}

	if ((err = at_tok_start(&p_cur)) >= 0)
	{
		err = at_tok_nextint (&p_cur, p_out);
	}

	return (err >= 0);
}

int at_line_scanf_int_int (char* p_cur, int* p_out1, int* p_out2)
{
	int err = 0;

	if (p_cur == NULL || p_out1 == NULL || p_out2 == NULL)
	{
		return 0;
	}
	
	do
	{
		if ((err = at_tok_start(&p_cur)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint (&p_cur, p_out1)) < 0)
		{
			break;
		}

		err = at_tok_nextint (&p_cur, p_out2);
	}while(0);

	return (err >= 0);
}

int at_line_scanf_int_int_int(char* p_cur, int* p_int1, int* p_int2, int* p_int3)
{
	int err = 0;

	if (p_cur == NULL || p_int1 == NULL || p_int2 == NULL || p_int3 == NULL)
	{
		return 0;
	}
	
	do
	{
		if ((err = at_tok_start(&p_cur)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint (&p_cur, p_int1)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint (&p_cur, p_int2)) < 0)
		{
			break;
		}

		err = at_tok_nextint (&p_cur, p_int3);
	}while(0);

	return (err >= 0);

}

int at_line_scanf_int_int_int_int (char* p_cur, int* p_out1, int* p_out2,
						int* p_out3, int* p_out4)
{
	int err = 0;

	if (p_cur == NULL || p_out1 == NULL || p_out2 == NULL 
			|| p_out3 == NULL || p_out4 == NULL)
	{
		return 0;
	}
	
	do
	{
		if ((err = at_tok_start(&p_cur)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint (&p_cur, p_out1)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint (&p_cur, p_out2)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint (&p_cur, p_out3)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint (&p_cur, p_out4)) < 0)
		{
			break;
		}
	}while(0);

	return (err >= 0);
}

int at_line_scanf_int_int_int_int_int (char* p_cur, int* p_out1, int* p_out2,
						int* p_out3, int* p_out4, int* p_out5)
{
	int err = 0;

	if (p_cur == NULL || p_out1 == NULL || p_out2 == NULL 
			|| p_out3 == NULL || p_out4 == NULL || p_out5 == NULL)
	{
		return 0;
	}
	
	do
	{
		if ((err = at_tok_start(&p_cur)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint (&p_cur, p_out1)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint (&p_cur, p_out2)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint (&p_cur, p_out3)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint (&p_cur, p_out4)) < 0)
		{
			break;
		}
		err = at_tok_nextint (&p_cur, p_out5);
	}while(0);

	return (err >= 0);
}

int at_line_scanf_string (char* p_cur, char** pp_out)
{
	int err = 0;

	if (p_cur == NULL || pp_out == NULL)
	{
		return 0;
	}

	if ((err = at_tok_start(&p_cur)) >= 0)
	{
		err = at_tok_nextstr (&p_cur, pp_out);
	}

	return (err >= 0);
}

int at_line_scanf_int_string(char* p_cur, int* p_int, char** pp_str)
{
	int err = 0;

	if (p_cur == NULL || p_int == NULL || pp_str == NULL)
	{
		return 0;
	}

	do
	{
		if((err = at_tok_start(&p_cur)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint(&p_cur, p_int)) < 0)
		{
			break;
		}

		if((err = at_tok_nextstr(&p_cur, pp_str)) < 0)
		{
			break;
		}
	}while(0);

	return (err >= 0);
}

int at_line_scanf_int_int_string(char* p_cur, int* p_int1, int* p_int2, char** pp_str)
{
	int err = 0;

	if (p_cur == NULL || p_int1 == NULL || p_int2 == NULL || pp_str == NULL)
	{
		return 0;
	}

	do
	{
		if((err = at_tok_start(&p_cur)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint(&p_cur, p_int1)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint(&p_cur, p_int2)) < 0)
		{
			break;
		}

		if((err = at_tok_nextstr(&p_cur, pp_str)) < 0)
		{
			break;
		}
	}while(0);

	return (err >= 0);
}

int at_line_scanf_int_string_int_string_int(char* p_cur, int* p_int1,
		char** pp_str1, int* p_int2, char** pp_str2, int* p_int3)
{
	int err = 0;

	if (p_cur == NULL || p_int1 == NULL || p_int2 == NULL || p_int3 == NULL
			|| pp_str1 == NULL || pp_str2 == NULL)
	{
		return 0;
	}

	do
	{
		if((err = at_tok_start(&p_cur)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint(&p_cur, p_int1)) < 0)
		{
			break;
		}

		if((err = at_tok_nextstr(&p_cur, pp_str1)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint(&p_cur, p_int2)) < 0)
		{
			break;
		}

		if((err = at_tok_nextstr(&p_cur, pp_str2)) < 0)
		{
			break;
		}
		
		if((err = at_tok_nextint(&p_cur, p_int3)) < 0)
		{
			break;
		}
	}while(0);

	return (err >= 0);

}
//wupeng add begin.
int at_line_scanf_string_int_int (char* p_cur, char** pp_str, int* p_int1, int* p_int2)
{
	int err = 0;

	if (p_cur == NULL || p_int1 == NULL || p_int2 == NULL || pp_str == NULL)
	{
		return 0;
	}

	do
	{
		if((err = at_tok_start(&p_cur)) < 0)
		{
			break;
		}

		if((err = at_tok_nextstr(&p_cur, pp_str)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint(&p_cur, p_int1)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint(&p_cur, p_int2)) < 0)
		{
			break;
		}
	}while(0);

	return (err >= 0);

}

//wupeng add end.

/* broncho yinlijun add begin */
int at_line_scanf_string_int_int_int_int (char* p_cur, char** pp_str, int* p_int1, int* p_int2, int* p_int3, int* p_int4)
{
	int err = 0;

	if (p_cur == NULL || p_int1 == NULL || p_int2 == NULL || pp_str == NULL || p_int3 == NULL || p_int4 == NULL)
	{
		return 0;
	}

	do
	{
		if((err = at_tok_start(&p_cur)) < 0)
		{
			break;
		}

		if((err = at_tok_nextstr(&p_cur, pp_str)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint(&p_cur, p_int1)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint(&p_cur, p_int2)) < 0)
		{
			break;
		}
		
		if((err = at_tok_nextint(&p_cur, p_int1)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint(&p_cur, p_int2)) < 0)
		{
			break;
		}
	}while(0);

	return (err >= 0);

}
/* broncho add end */

int at_line_scanf_string_int_int_int_int_int(char* p_cur, char** pp_str, 
						int* p_int1, int* p_int2, int* p_int3, int* p_int4, int* p_int5)
{
	int err = 0;

	if(p_cur == NULL || pp_str == NULL || p_int1 == NULL 
		|| p_int2 == NULL || p_int3 == NULL || p_int4 == NULL)
	{
		return 0;
	}

	do
	{
		if((err = at_tok_start(&p_cur)) < 0)
		{
			break;
		}

		if((err = at_tok_nextstr(&p_cur, pp_str)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint(&p_cur, p_int1)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint(&p_cur, p_int2)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint(&p_cur, p_int3)) < 0)
		{
			break;
		}
		if((err = at_tok_nextint(&p_cur, p_int4)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint(&p_cur, p_int5)) < 0)
		{
			break;
		}
		
	}while(0);

	return (err >= 0);

}

int at_line_scanf_int_int_int_int_int_int_int_int(char* p_cur, int* p_int1, int* p_int2,
		int* p_int3, int* p_int4, int* p_int5, int* p_int6, int* p_int7, int* p_int8)
{
	int err = 0;

	if(p_cur == NULL || p_int1 == NULL 
		|| p_int2 == NULL || p_int3 == NULL || p_int4 == NULL || p_int5 == NULL
		|| p_int6 == NULL || p_int7 == NULL || p_int8 == NULL)
	{
		return 0;
	}

	do
	{
		if((err = at_tok_start(&p_cur)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint(&p_cur, p_int1)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint(&p_cur, p_int2)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint(&p_cur, p_int3)) < 0)
		{
			break;
		}
		if((err = at_tok_nextint(&p_cur, p_int4)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint(&p_cur, p_int5)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint(&p_cur, p_int6)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint(&p_cur, p_int7)) < 0)
		{
			break;
		}

		if((err = at_tok_nextint(&p_cur, p_int8)) < 0)
		{
			break;
		}

	}while(0);

	return (err >= 0);


}

int at_line_scanf_string_string_string(char* p_cur, char** pp_str1,
		char** pp_str2, char** pp_str3)
{
	int err = 0;

	if (p_cur == NULL || pp_str1 == NULL || pp_str2 == NULL || pp_str3 == NULL)
	{
		return 0;
	}
	
	do
	{
		if ((err = at_tok_start(&p_cur)) < 0)
		{
			break;
		}

		if((err = at_tok_nextstr (&p_cur, pp_str1)) < 0)
		{
			break;
		}
		
		if((err = at_tok_nextstr (&p_cur, pp_str2)) < 0)
		{
			break;
		}

		if((err = at_tok_nextstr (&p_cur, pp_str3)) < 0)
		{
			break;
		}
	}while(0);

	return (err >= 0);
}

int at_line_scanf_string_string_string_string_string_string(char* p_cur, char** pp_str1,
		char** pp_str2, char** pp_str3, char** pp_str4, char** pp_str5, char** pp_str6)
{
	int err = 0;

	if (p_cur == NULL || pp_str1 == NULL || pp_str2 == NULL || pp_str3 == NULL
		 	|| pp_str4 == NULL || pp_str5 == NULL || pp_str6 == NULL)
	{
		return 0;
	}
	
	do
	{
		if ((err = at_tok_start(&p_cur)) < 0)
		{
			break;
		}

		if((err = at_tok_nextstr (&p_cur, pp_str1)) < 0)
		{
			break;
		}
		
		if((err = at_tok_nextstr (&p_cur, pp_str2)) < 0)
		{
			break;
		}

		if((err = at_tok_nextstr (&p_cur, pp_str3)) < 0)
		{
			break;
		}

		if((err = at_tok_nextstr (&p_cur, pp_str4)) < 0)
		{
			break;
		}
		
		if((err = at_tok_nextstr (&p_cur, pp_str5)) < 0)
		{
			break;
		}

		if((err = at_tok_nextstr (&p_cur, pp_str6)) < 0)
		{
			break;
		}
	}while(0);

	return (err >= 0);

}

void sleep_msec(long long msec)
{
    struct timespec ts;
    int err;

    ts.tv_sec = (msec / 1000);
    ts.tv_nsec = (msec % 1000) * 1000 * 1000;

    do {
        err = nanosleep (&ts, &ts);
    } while (err < 0 && errno == EINTR);
}

static int open_serial_port (const char* serial_tio_name)
{
    int fd = 0;
    struct termios newtio_p;
	unsigned int tio_baudrate = B115200;

	fd = open (serial_tio_name, O_RDWR | O_NOCTTY | O_NDELAY);
    if (fd <0)
    {   
        ALOGE("%s errno: %s, port name %s", __func__, strerror(errno), serial_tio_name);
        return 0;
    }

    bzero(&newtio_p, sizeof(newtio_p));

	//fcntl(fd, F_SETFL, 0);
#ifdef USE_CRTSCTS
	newtio_p.c_cflag = CLOCAL | CREAD | CS8 | HUPCL | tio_baudrate | CRTSCTS;
#else
	newtio_p.c_cflag = CLOCAL | CREAD | CS8 | HUPCL | tio_baudrate;
#endif

	newtio_p.c_cflag &= ~tio_baudrate;
	newtio_p.c_cflag |= tio_baudrate;

//	newtio_p.c_iflag = IGNBRK;	
	newtio_p.c_iflag  = IGNBRK | IGNPAR;
    newtio_p.c_iflag &= ~(INLCR | ICRNL | IGNCR);;
    /* set input mode */
    newtio_p.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

	// set raw output
	newtio_p.c_oflag &= ~OPOST;
	newtio_p.c_oflag &= ~OLCUC;
	newtio_p.c_oflag &= ~ONLRET;
	newtio_p.c_oflag &= ~ONOCR;
	newtio_p.c_oflag &= ~OCRNL;

    tcflush(fd, TCIFLUSH);
    tcsetattr(fd, TCSANOW, &newtio_p);

    return fd;
}

static int open_pty (const char* serial_tio_name)
{
    int fd = 0;
	struct termios newtio_p;
   	
	memset(&newtio_p, 0, sizeof(struct termios));
    fd = open(serial_tio_name, O_RDWR | O_NONBLOCK);
    if (fd <0)
    {
        perror(serial_tio_name);
        return 0;
    }

    // get the parameters
    bzero(&newtio_p, sizeof(newtio_p));
    tcgetattr(fd, &newtio_p);
    // set raw input
    newtio_p.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

	newtio_p.c_iflag = IGNBRK;
    newtio_p.c_iflag &= ~(INLCR | ICRNL | IGNCR);

    // set raw output
    newtio_p.c_oflag &= ~OPOST;
    newtio_p.c_oflag &= ~OLCUC;
    newtio_p.c_oflag &= ~ONLRET;
    newtio_p.c_oflag &= ~ONOCR;
    newtio_p.c_oflag &= ~OCRNL;
	tcflush(fd, TCIFLUSH);
    tcsetattr(fd, TCSANOW, &newtio_p);

    return fd;
}

static int ril_device_open (const char* serial_tio_name)
{
	int fd = -1;

    if (strncmp (serial_tio_name, TTY_DEVICE_PREFIX, strlen (TTY_DEVICE_PREFIX)) == 0)
    {
		fd = open_serial_port (serial_tio_name);
    }
    else
    {
		fd = open_pty (serial_tio_name);
    }

	return fd;
}

int ril_open_port(RilPortType type, const char* port_name)
{
	int fd = -1;

	switch(type)
	{
	case PORT_TYPE_SOCKET:
		fd = socket_local_client( port_name,
				ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
		break;

	case PORT_TYPE_PTY:
	case PORT_TYPE_SERIAL:
		fd = ril_device_open(port_name);
		break;

	case PORT_TYPE_LOOPBACK:
		fd = socket_loopback_client((int)port_name, SOCK_STREAM);
		break;

	default:
		break;
	}

	return fd;
}

void putuint8(unsigned char*data, unsigned short startBit, 
		unsigned char numBits, unsigned char value)
{
	unsigned char startByteIndex = 0;
	unsigned char startBitIndex = 0;
	int  bitsIn2ndByte = 0;
	int  lowBitsSave1stByte = 0;
	unsigned char temp = 0;
	unsigned char mask;

	startByteIndex = (unsigned char)(startBit >> 3);
	startBitIndex  = (unsigned char)(startBit & 0x7);
	bitsIn2ndByte = startBitIndex + numBits - 8;

	if (bitsIn2ndByte > 0)
	{
		mask = _saveTopMask[ startBitIndex ];
		data[ startByteIndex ] &= mask;
		data[ startByteIndex ] |= (~mask & (value >> bitsIn2ndByte));
		data[ startByteIndex + 1 ] &= ~_saveTopMask[ (unsigned char) bitsIn2ndByte ];
		data[ startByteIndex + 1 ] |= (value << (8 - bitsIn2ndByte));
	}
	else
	{
		lowBitsSave1stByte = -bitsIn2ndByte;
		mask = _valueMask[numBits] << lowBitsSave1stByte;
		temp  = data[ startByteIndex ] & ~mask;
		data[ startByteIndex ] = temp | ( mask & (value << lowBitsSave1stByte));
	}

	return;
}

unsigned char getuint8(unsigned char* data, unsigned int startBit, 
				unsigned int numBits)
{
	unsigned char startByteIndex = 0;
	unsigned char startBitIndex = 0;
	unsigned char value = 0;
	int  bitsIn2ndByte = 0;

	startByteIndex = (unsigned char)(startBit >> 3);
	startBitIndex  = (unsigned char)(startBit & 0x07);
	
	value = (data[ startByteIndex ] & _bitValueMask[ startBitIndex ]);

	bitsIn2ndByte = numBits + startBitIndex - 8;
	if( bitsIn2ndByte > 0 )
	{
		value = ((value << bitsIn2ndByte) | (data[startByteIndex+1] >> (8 - bitsIn2ndByte)));
	}
	else
	{
		value = value >> -bitsIn2ndByte;
	}

	return value;
}

unsigned char bcdToChar(int b)
{
	if (b < 0xa) {
		return (char)('0' + b);
	} else switch (b) {
		case 0x0:
		case 0xa: return '0';
		case 0xb: return '*';
		case 0xc: return '#';

		default: return 0;
	}
}

int charToBcd(char c)
{
	int ret = 0;

	if(c == '0') {
		ret = 0xa;
	} else if (c >= '0' && c <= '9') {
		ret = c - '0';
	} else if (c == '*') {
		ret = 0xb;
	} else if (c == '#') {
		ret = 0xc;
	}

	return ret;
}
//wupeng modify begin.
//static unsigned char hextodec(unsigned char* pch)
unsigned char hextodec(unsigned char* pch)
//wupeng modify end.
{
	unsigned char oneby;
	unsigned char ch;

	ch = *pch;
	ch = upper(ch);
	if( (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') )
	{
		oneby = ((ch >='A')?(10+ch-'A'):(ch-'0'))*16;
	}
	else{
		return 0;
	}

	pch++;
	ch = *pch;
	ch = upper(ch);
	if( (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') )
	{
		oneby += (ch >='A')?(10+ch-'A'):(ch-'0');
	}
	else
	{
		oneby = 0;
	}

	return oneby;
}

unsigned char* StringToHex(unsigned char *pSrc ,int dSrcLen)
{
	int   i = 0;
	unsigned char* ret = calloc(1, dSrcLen / 2);

	for (i = 0 ; i < dSrcLen / 2; i++)
	{
		*(ret + i) = hextodec (pSrc+ 2*i);
	}
	return ret;
}

char* hexToString(unsigned char *psrc , int srclen)
{
	char* ret = NULL;
	int  i = 0;

	ret = calloc(1, srclen * 2 + 1);
	for(i = 0; i < srclen; i++)
	{
		sprintf(ret+2*i,"%02X",psrc[i]);
	}

	return ret;
}

static void PrintHex (register unsigned char * out, const unsigned char * in, int count)
{
	register unsigned char next_ch;
	static char hex[] = "0123456789ABCDEF";

	while (count-- > 0)
	{
		next_ch = *in++;
		*out++ = hex[(next_ch >> 4) & 0x0F];
		*out++ = hex[next_ch & 0x0F];        ++out;
	}
}

static void PrintChar (register unsigned char * out, const unsigned char * in, int count)
{
	register unsigned char next_ch;

	while (count-- > 0)
	{
		next_ch = *in++;
		if (next_ch < 0x20 || next_ch > 0x7e)
			*out++ = '.';
			else
			{
				*out++ = next_ch;
				if (next_ch == '%')   /* ALOGD/syslogd has a bug !! */
					*out++ = '%';
			}
	}

	*out = '\0';
}

void PrintBuffer (const char *name, const unsigned char *buf, int count)
{
	unsigned char line[44*4]; 

	if (name != NULL)
		ALOGD("%s,n=%d\n", name, count);

	while (count > 6*4)
	{
		memset (line, 32, 44*4);
		PrintHex (line, buf, 6*4);
		PrintChar (&line[6 * 3*4], buf, 6*4);
		ALOGD("%s\n", line);
		count -= 6*4;
		buf += 6*4;
	}

	if (count > 0)
	{
		memset (line, 32, 44*4);
		PrintHex (line, buf, count);        PrintChar (&line[6 * 3*4], buf, count);
		ALOGD( "%s\n", line);
	}
}

int             CheckPlatform(const char* platform)
{
	int ret = 0;
	int fd = 0;
	
	fd = open(PLATFORM_PATH, O_RDWR | O_NONBLOCK);
	if(fd > 0)
	{
		char buf[256] = {0};
		
		if(read(fd, buf, 255) > 0)
		{
			if(strstr(buf, platform) != NULL)
			{
				ret = 1;
			}
		}
		
		close(fd);
	}

	return ret;

}

int calibrateSignalStrength(int sig)
{
	int ret = sig;

	if(sig > 2 && sig < 12)
	{
		ret += 4;
	}
	else if(sig > 12 && sig < 16)
	{
		ret = 16; 
	}

	return ret;
}

/*broncho yinlijun add begin*/
int gethex(const char * hexstring, int size)
{
	int re = 0;
	int tmp = 0;
	char* str = hexstring;

	while( ( NULL != *str ) && ( hexstring+size != str ) )
	{
		if ( *str >= '0' && *str <= '9' )
			tmp = *str - '0';
		else if ( *str >= 'a' && *str <= 'z' )
			tmp = *str - 'a' + 10;
		else if ( *str >= 'A' && *str <= 'Z' )
			tmp = *str - 'A' + 10;
		else
			return 0;

		re = re * 16 + tmp;
		++str;
	}
	return re;
}

void hex_dump(void *data, int size)
{
	/* dumps size bytes of *data to stdout. Looks like:
	 * [0000] 75 6E 6B 6E 6F 77 6E 20
	 *				  30 FF 00 00 00 00 39 00 unknown 0.....9.
	 * (in a single line of course)
	 */

	unsigned char *p = data;
	unsigned char c;
	int n;
	char bytestr[4] = {0};
	char addrstr[10] = {0};
	char hexstr[ 16*3 + 5] = {0};
	char charstr[16*1 + 5] = {0};
	for(n=1;n<=size;n++) {
		if (n%16 == 1) {
			/* store address for this line */
			snprintf(addrstr, sizeof(addrstr), "%.4x",
			   ((unsigned int)p-(unsigned int)data) );
		}

		c = *p;
		if (isalnum(c) == 0) {
			c = '.';
		}

		/* store hex str (for left side) */
		snprintf(bytestr, sizeof(bytestr), "%02X ", *p);
		strncat(hexstr, bytestr, sizeof(hexstr)-strlen(hexstr)-1);

		/* store char str (for right side) */
		snprintf(bytestr, sizeof(bytestr), "%c", c);
		strncat(charstr, bytestr, sizeof(charstr)-strlen(charstr)-1);

		if(n%16 == 0) {
			/* line completed */
			ALOGD("[%4.4s]   %-50.50s  %s", addrstr, hexstr, charstr);
			hexstr[0] = 0;
			charstr[0] = 0;
		} else if(n%8 == 0) {
			/* half line: add whitespaces */
			strncat(hexstr, "  ", sizeof(hexstr)-strlen(hexstr)-1);
			strncat(charstr, " ", sizeof(charstr)-strlen(charstr)-1);
		}
		p++; /* next byte */
	}

	if (strlen(hexstr) > 0) {
		/* print rest of buffer if not empty */
		ALOGD("[%4.4s]   %-50.50s  %s\n", addrstr, hexstr, charstr);
	}
}
/* broncho yinlijun add end */

